home *** CD-ROM | disk | FTP | other *** search
/ Trading on the Edge / Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin / pc / mac_file / vendor_d / neuralwa / nw2v50 / usermstd.c < prev    next >
Text File  |  1993-08-23  |  18KB  |  634 lines

  1. /* $Id$ */
  2. /* $Log$ */
  3. /* 12-24-90 (usermath.c)   User-Defined Neuro-Dynamics Prototype */
  4. /************************************************************************
  5.  * Copyright(C) 1987-1992 NeuralWare Inc                                *
  6.  * Penn Center West, IV-227, Pittsburgh, PA 15276                       *
  7.  * Telephone: (412) 787-8222    FAX: (412) 787-8220                     *
  8.  *                                                                      *
  9.  * All rights reserved.  No part of this program may be reproduced,     *
  10.  * stored in a retrieval system, or transmitted, in any form or by any  *
  11.  * means, electronic, mechanical, photocopying, recording or otherwise  *
  12.  * without the prior written permission of the copyright owner,         *
  13.  * NeuralWare, Inc.                                                     *
  14.  *                                                                      *
  15.  *                          PROPRIETARY NOTICE                          *
  16.  *                                                                      *
  17.  * This document is the property of NeuralWare, Inc. and contains       *
  18.  * trade-secrets and other proprietary information.  The information    *
  19.  * herein is reserved as proprietary to NeuralWare, and is not to be    *
  20.  * published, reproduced, copied, disclosed, used, or reverse           *
  21.  * engineered without the express written consent of a duly authorized  *
  22.  * representative of NeuralWare.                                        *
  23.  ************************************************************************
  24.  */
  25.  
  26.  
  27. #define USERMATH
  28.  
  29. #include <math.h>
  30. #ifdef DPTEST
  31. #include "nn_run.h"
  32. #else
  33. #include "usermath.h"
  34. #endif
  35.  
  36. #ifndef DPTEST
  37.  
  38. #define USER_BACKPROP 1
  39. #undef USER_BACKPROP
  40.  
  41. /* Useful preprocessor macros */
  42. /* (a) Recall Schedule Macros: */
  43. #define RCOLP   (ulp->r_col_p)  /* Recall column pointer */
  44. #define RCOLX   (ulp->r_col_x)  /* Recall column index */
  45. #define RSTEP   (RCOLP->rstep)
  46. #define CLAMP   (RCOLP->iclamp)
  47. #define FIRE    (RCOLP->fire)
  48. #define RTEMP   (RCOLP->rtemp)
  49. #define MODF    (RCOLP->modf)
  50. #define GAIN    (RCOLP->gain)
  51. #define RCOEF5  (RCOLP->rcoef[0])
  52. #define RCOEF6  (RCOLP->rcoef[1])
  53. #define RCOEF7  (RCOLP->rcoef[2])
  54. #define RCOEF8  (RCOLP->rcoef[3])
  55. #define RCOEF9  (RCOLP->rcoef[4])
  56. /* (b) Learn Schedule Macros: */
  57. #define LCOLP   (ulp->l_col_p)  /* Learn column pointer */
  58. #define LCOLX   (ulp->l_col_x)  /* Learn column index */
  59. #define LSTEP   (LCOLP->lcount)
  60. #define LTEMP   (LCOLP->ltemp)
  61. #define LCOEF1  (LCOLP->lcoef1)
  62. #define LCOEF2  (LCOLP->lcoef2)
  63. #define LCOEF3  (LCOLP->lcoef3)
  64. #define LCOEF4  (LCOLP->lcoef[0])
  65. #define LCOEF5  (LCOLP->lcoef[1])
  66. #define LCOEF6  (LCOLP->lcoef[2])
  67. #define LCOEF7  (LCOLP->lcoef[3])
  68. #define LCOEF8  (LCOLP->lcoef[4])
  69. #define LCOEF9  (LCOLP->lcoef[5])
  70. /* (c) Network Counter Macros: */
  71. #define RCOUNT  (um_ctr[CTR_RECALL])
  72. #define LAYERN  (um_ctr[CTR_LAYER])
  73. #define LCOUNT  (um_ctr[CTR_LEARN])
  74. #define AUX1    (um_ctr[CTR_AUX1])
  75. #define AUX2    (um_ctr[CTR_AUX2])
  76. #define AUX3    (um_ctr[CTR_AUX3])
  77. #define WORK1   (um_ctr[CTR_WRK1])
  78. #define WORK2   (um_ctr[CTR_WRK2])
  79. /* (d) Layer Parameter macros: */
  80. #define SCALE   (ulp->scale)
  81. #define OFFST   (ulp->offset)
  82. #define LO_CLIP (ulp->lo_clip)
  83. #define HI_CLIP (ulp->hi_clip)
  84. #define FP_OFF  (ulp->fprime_off)
  85.  
  86. #define EXPLIM  12.0    /* limit for exponentials to be fixed */
  87.  
  88. #endif  /* DPTEST */
  89.  
  90. #ifndef DPK
  91. /* um_event() is called whenever a significant event occurs which might
  92.    require attention by this particular usermath routine.  It is ONLY
  93.    called if the current network uses a user-math function in one of
  94.    its layers. */
  95.  
  96. #if defined(ANSI_HEADER)
  97.  
  98. NINT    um_event( XB *netnp, XB *csnp, USR_LYR *SLayerp, NINT code )
  99.  
  100. #else
  101.  
  102. NINT    um_event( netnp, csnp, SLayerp, code )
  103. XB    *netnp;     /* network name (ascii) */
  104. XB    *csnp;      /* control strategy name pointer */
  105. USR_LYR   *SLayerp;   /* current super-layer pointer */
  106. NINT     code;      /* event code */
  107.  
  108. #endif
  109. {
  110.    NINT   rc;    /* return code */
  111.    
  112.    rc = 0;
  113. #ifndef DPTEST
  114.    switch( code ) {
  115.     case UME_LSTART:    /* start of learning */
  116.       rc = 1; break;
  117.     case UME_LEND:    /* end of learning */
  118.       rc = 2; break;
  119.     case UME_TSTART:    /* start of recall test */
  120.       rc = 3; break;
  121.     case UME_RSTART:    /* start of recall */
  122.       rc = 4; break;
  123.     case UME_REND:    /* end of recall */
  124.       rc = 5; break;
  125.     case UME_LOAD:    /* network has been loaded */
  126.       rc = 6; break;
  127.     case UME_SAVE:    /* network is about to be saved */
  128.       rc = 7; break;
  129.     case UME_DELETE:    /* network is about to be deleted */
  130.       rc = 8; break;
  131.       
  132.     default:
  133.       rc = 9; break;
  134.    }
  135. #endif /* DPTEST */   
  136.    return( rc );
  137. }
  138.  
  139.  
  140.  
  141. /* um_chkpt is called when User check-pointing is active in the NWorks
  142.    Run/CheckPoints dialog box.  um_chkpt( ) is called at the requested
  143.    checkpoints for each PE in each layer with a User Math function. */
  144.  
  145. #if defined(ANSI_HEADER)
  146.  
  147. NINT um_chkpt( USR_PE *upep, USR_CN_HDR *uchp, USR_LYR *ulp)
  148.  
  149. #else
  150.  
  151. NINT um_chkpt( upep, uchp, ulp )
  152. USR_PE    *upep;      /* Pointer to current PE */
  153. USR_CN_HDR  *uchp;      /* Pointer to connection header */
  154. USR_LYR   *ulp;
  155.  
  156. #endif
  157. {
  158.    NINT   rc;    /* return code */
  159.    
  160.    rc = 0;
  161.    return( rc );
  162. }
  163.  
  164. #endif /* DPK */
  165.  
  166. #ifndef DPTEST
  167. #ifndef DPK
  168. /* */
  169. /* The um_s_user routines are called if the "sum" bit of the math microcode
  170.    is set and a user summation function is selected in the summation
  171.    scroll window of the layer dialog box */
  172.  
  173. #ifdef USER_BACKPROP
  174. /* bkpstdSum */
  175.  
  176. #if defined(ANSI_HEADER)
  177.  
  178. NINT um_s_backprop( USR_PE *upep, USR_CN_HDR *uchp, USR_LYR *ulp)
  179.  
  180. #else
  181.  
  182. NINT um_s_backprop(upep, uchp, ulp)
  183. USR_PE    *upep;      /* Pointer to current PE */
  184. USR_CN_HDR  *uchp;      /* Pointer to connection header */
  185. USR_LYR   *ulp;
  186.  
  187. #endif
  188. {
  189.    USR_CONN  *ct;      /* Connection Table */
  190.    NINT     wx, wf;
  191.    REAL     wv, accum;
  192.    NINT     sizewts;
  193.    
  194.    if ( IS_INIT )
  195.       return (0);
  196.    if ( IS_PRE_POST ) 
  197.       return 0;
  198.    accum = 0.0;
  199.    sizewts = ulp->functions.size_wts;
  200.    for ( wx = 0, ct = &uchp->conn_table[0];
  201.         wx < uchp->num_conns; wx++, UPDWXP(ct,sizewts) ) {
  202.       wf = ct->flag;
  203.       wv = ct->weight;
  204.       if ( (wf & CN_DISABLED) != 0 ) continue;
  205.       wf &=  CN_WT_MASK;
  206.       if (      wf == CN_SET )  wv *= CLAMP;
  207.       else if ( wf == CN_MOD )  wv *= MODF;
  208.       accum += ( ct->src_pe->out_val * wv);
  209.    }
  210.    upep->sum_val = accum;
  211.    return(0);
  212. }
  213. #endif
  214. /* */
  215. /***********************************************************************
  216.  *
  217.  *  User Transform routines
  218.  *
  219.  ***********************************************************************
  220.  */
  221.  
  222. /* The um_t_user routines are called in any of three cases :
  223.    
  224.    > an INIT button is selected, which sets the UMCF_INIT flag
  225.    
  226.    > the "e*=f'" bit is selected, which sets the UMCF_DERIV flag
  227.    
  228.    > if the "tran" bit of the math microcode is set and a user transfer 
  229.    function is selected in the current layer. ( neither UMCF_INIT
  230.    nor UMCF_DERIV will be set )
  231.    */
  232.  
  233.  
  234. #ifdef USER_BACKPROP
  235. #if defined(ANSI_HEADER)
  236.  
  237. NINT um_t_backprop( USR_PE *upep, USR_CN_HDR *uchp, USR_LYR *ulp)
  238.  
  239. #else
  240.  
  241. NINT um_t_backprop(upep, uchp, ulp)
  242. USR_PE    *upep;    /* Pointer to current PE */
  243. USR_CN_HDR  *uchp;    /* Pointer to connection header */
  244. USR_LYR   *ulp;   /* Pointer to current layer */
  245.  
  246. #endif
  247.  
  248. {
  249.    REAL     wr;      /* work real */
  250.    REAL     rv;      /* random value */
  251.    
  252.    if ( IS_INIT )
  253.       return (0);
  254.    
  255.    if ( IS_PRE_POST )
  256.       return (0);
  257.    
  258.    if ( IS_DERIV ) {
  259.       if ( fabs( SCALE ) < NRZRO ) {
  260.          upep->err_val = 0.0;
  261.       } else {
  262.          upep->err_val /= SCALE;     /* remove scaling from error */
  263.          /* Strip off scale and offset from tran value */
  264.          wr = ( upep->trn_val - OFFST ) / SCALE;
  265.          wr = wr * (1.0-wr) * GAIN;
  266.          wr += FP_OFF;
  267.          
  268.          upep->err_val *= wr;
  269.       }
  270.    }
  271.    else /* not DERIV */ {
  272.       wr = upep->sum_val * GAIN;  /* value to work with */
  273.       
  274.       rv = 0.0;
  275.       if ( (um_micro & MF_LNOISE) != 0 ) rv += LTEMP;
  276.       if ( (um_micro & MF_RNOISE) != 0 ) rv += RTEMP;
  277.       if ( rv > 0.0 ) {
  278.          rv = 0.02 * rv;   /* scale to 2 * percentage */
  279.          wr += rv * ( nrand(  ) * RANDINV - 0.5 ); /* add noise */
  280.       }
  281.       
  282.       if ( wr > EXPLIM )  wr = 1.0;
  283.       else if ( wr < -EXPLIM )  wr = 0.0;
  284.       else wr = 1.0 / ( 1.0 + exp( -wr ) );
  285.       /* Offset, scale and hard limit */
  286.       upep->trn_val = SCALE * wr + OFFST;
  287.       if ( upep->trn_val < LO_CLIP ) upep->trn_val = LO_CLIP;
  288.       if ( upep->trn_val > HI_CLIP ) upep->trn_val = HI_CLIP;
  289.    }
  290.    return (0);
  291. }
  292. #endif
  293. /***********************************************************************
  294.  *
  295.  *  User Defined Output Functions
  296.  *
  297.  ***********************************************************************
  298.  */
  299.  
  300. /* The um_o_user routines are called if the "output" bit of the math microcode
  301.    is set and a user output function is selected in the output function
  302.    scroll window of the layer dialog box */
  303.  
  304.  
  305. /***********************************************************
  306.  *
  307.  * This is here for compatibility with prevoius versions of PNN
  308.  *
  309.  ***********************************************************
  310.  */
  311.  
  312. #if defined(ANSI_HEADER)
  313.  
  314. NINT um_o_pnn( USR_PE *upep, USR_CN_HDR *uchp, USR_LYR *ulp)
  315.  
  316. #else
  317.  
  318. NINT um_o_pnn(upep, uchp, ulp)
  319. USR_PE    *upep;    /* Pointer to current PE */
  320. USR_CN_HDR  *uchp;    /* Pointer to connection header */
  321. USR_LYR   *ulp;   /* Pointer to current layer */
  322.  
  323. #endif
  324.  
  325. {
  326.    LOCAL  found;
  327.    
  328.    if ( IS_INIT )
  329.       return (0);
  330.    
  331.    if ( IS_PRELYR ) found = 0; /* Start of lyr */
  332.    if ( IS_PRE_POST )  return (0);
  333.    if ( upep->flag&PE_NOT_LEARNED ) {    /* Not yet lrned */
  334.       upep->out_val = 0.0;      /* Zero output */
  335.       /* If learn PE not yet found, see if this is the one */
  336.       if ( !found && upep->err_val > NRZRO ) {
  337.          ulp->pe_kcur = upep;      /* This PE lrns */
  338.          found = 1;        /* Stop looking */
  339.       }
  340.    } else {
  341.       upep->out_val = upep->trn_val;    /* Direct output */
  342.    }
  343.    return ( 0 );
  344. }
  345. /***********************************************************************
  346.  *
  347.  *  User Defined Error Functions
  348.  *
  349.  ***********************************************************************
  350.  */
  351.  
  352. /* The um_e_user routines are called if the "e-=w" bit of the math microcode
  353.    is set and an error function is selected in the error function
  354.    scroll window of the layer dialog box */
  355.  
  356.  
  357. #ifdef USER_BACKPROP
  358. #if defined(ANSI_HEADER)
  359.  
  360. NINT um_e_backprop( USR_PE *upep, USR_CN_HDR *uchp, USR_LYR *ulp)
  361.  
  362. #else
  363.  
  364. NINT um_e_backprop(upep, uchp, ulp)
  365. USR_PE    *upep;    /* Pointer to current PE */
  366. USR_CN_HDR  *uchp;    /* Pointer to connection header */
  367. USR_LYR   *ulp;   /* Pointer to current layer */
  368.  
  369. #endif
  370.  
  371. {
  372.    if ( IS_INIT )
  373.       return (0);
  374.    
  375.    if ( IS_PRE_POST )  return ( 0 );
  376.    
  377.    upep->err_val = upep->err_val - upep->trn_val;
  378.    
  379.    /* check for apriori error modifications */
  380.    if ( (um_micro & MF_ERRFAC) != 0 )
  381.       upep->err_val *= upep->err_fac;
  382.    
  383.    /* special variant of back-propagation */
  384.    if( fabs( upep->err_val ) < LCOEF3 )
  385.       upep->err_val = 0.0;
  386.    return (0);
  387. }
  388. #endif
  389.  
  390. /***********************************************************************
  391.  *
  392.  *  User Defined Learn Functions
  393.  *
  394.  ***********************************************************************
  395.  */
  396.  
  397. /* The um_l_user routines are called if the "learn" bit of the math microcode
  398.    is set and a user learn function is selected in the learn function
  399.    scroll window of the layer dialog box */
  400.  
  401. /***********************************************************
  402.  * This has been kept in for compatibility reasons to
  403.  * support old versions of PNN.
  404.  *
  405.  * This is a general Kohonen type learning where it is
  406.  * assumed that the output function has set the pe_kcur
  407.  * field of ulp to point to the PE which should learn.
  408.  * When um_flag has its UMCF_POSTLYR bit set, upep is set
  409.  * to ulp->pe_kcur and uchp is set to the connection
  410.  * header for upep.  Consequently this section of code
  411.  * need only be entered when the UCMF_POSTLYR bit is set.
  412.  * It is required that the output and learn functions
  413.  * appear on the same control strategy math instruction
  414.  * line.
  415.  ***********************************************************
  416.  */
  417.  
  418.  
  419. #if defined(ANSI_HEADER)
  420.  
  421. NINT um_l_kohonen( USR_PE *upep, USR_CN_HDR *uchp, USR_LYR *ulp)
  422.  
  423. #else
  424.  
  425. NINT um_l_kohonen(upep, uchp, ulp)
  426. USR_PE    *upep;    /* Pointer to current PE */
  427. USR_CN_HDR  *uchp;    /* Pointer to connection header */
  428. USR_LYR   *ulp;   /* Pointer to current layer */
  429.  
  430. #endif
  431.  
  432. {
  433.    REAL     lcoef, wv;
  434.    NINT     wx;
  435.    USR_CONN  *ct;      /* Connection Table */
  436.    REAL     ssw;     /* Sum of squared weights */
  437.    REAL     issw;      /* Inverse sum of squared weights */
  438.    NINT     sizewts;
  439.    
  440.    if (ulp)
  441.       sizewts = ulp->functions.size_wts;
  442.    
  443.    if ( IS_INIT ) {
  444.       if ( IS_PRE_POST ) return (0);
  445.       upep->flag |= PE_NOT_LEARNED;
  446.       /* sum squared weights of variable connections entering PE */
  447.       ssw = 0.0;
  448.       for ( wx = 0, ct = &uchp->conn_table[0];
  449.            wx < (NINT)uchp->num_conns; wx++, UPDWXP(ct,sizewts) ) {
  450.          if ( (ct->flag & (CN_DISABLED|CN_WT_MASK)) != CN_VAR )
  451.             continue;     /* Not a variable weight */
  452.          ct->flag &= ~CN_USER;   /* Initialize User Flag */
  453.          ssw += ct->weight * ct->weight; /* Sum squared weights */
  454.          ct->last_dw = 0.0;    /* Zero out Delta Weight */
  455.       }
  456.       
  457.       if ( ssw > NRZRO ) {
  458.          issw = 1.0 / sqrt( ssw );
  459.          /* Normalize the enabled variable weights to length 1.0 */
  460.          for ( wx = 0, ct = &uchp->conn_table[0];
  461.               wx < (NINT)uchp->num_conns; wx++, UPDWXP(ct,sizewts) ) {
  462.             if ( (ct->flag & (CN_DISABLED|CN_WT_MASK)) != CN_VAR )
  463.                continue;     /* Not a variable weight */
  464.             ct->weight = issw * ct->weight;
  465.          }
  466.       }
  467.    }
  468.    else { /* not INIT */
  469.       if ( IS_POSTLYR ) {
  470.          if ( upep == (USR_PE *)0 )
  471.             return ( 0 );
  472.          
  473.          /* Calculate learning coefficient */
  474.          lcoef = LCOEF1;
  475.          if ( lcoef < NRZRO )
  476.             return ( 0 );
  477.          if ( upep->flag & PE_NOT_LEARNED )
  478.             lcoef = 1.0;      /* fast initial learning */
  479.          
  480.          /* dW = alpha * ( W - Input ) */
  481.          
  482.          for ( wx = 0, ct = &uchp->conn_table[0];
  483.               wx < (NINT)uchp->num_conns;
  484.               wx++, UPDWXP(ct,sizewts) ) {
  485.             if ( (ct->flag & (CN_DISABLED|CN_WT_MASK)) != CN_VAR )
  486.                continue;     /* Not a variable weight */
  487.             
  488.             /* compute the weight change */
  489.             wv = lcoef * ( ct->src_pe->out_val - ct->weight );
  490.             
  491.             /* change the weights */
  492.             ct->last_dw = wv;
  493.             ct->weight += wv;
  494.          }
  495.          upep->flag &= ~PE_NOT_LEARNED;    /* PE has learned */
  496.       }
  497.    }
  498.    return ( 0 );
  499. }
  500.  
  501.  
  502. #ifdef USER_BACKPROP
  503. #if defined(ANSI_HEADER)
  504.  
  505. NINT um_l_backprop( USR_PE *upep, USR_CN_HDR *uchp, USR_LYR *ulp)
  506.  
  507. #else
  508.  
  509. NINT um_l_backprop(upep, uchp, ulp)
  510. USR_PE    *upep;    /* Pointer to current PE */
  511. USR_CN_HDR  *uchp;    /* Pointer to connection header */
  512. USR_LYR   *ulp;   /* Pointer to current layer */
  513.  
  514. #endif
  515.  
  516. {
  517.    REAL     lcoef, wv;
  518.    NINT     wx;
  519.    USR_CONN  *ct;      /* Connection Table */
  520.    NINT     sizewts;
  521.    
  522.    if ( IS_INIT )
  523.       return (0);
  524.    
  525.    if ( IS_PRE_POST )  return ( 0 );
  526.    
  527.    lcoef = LCOEF1 * upep->err_val;
  528.    
  529.    sizewts = ulp->functions.size_wts;
  530.    
  531.    for ( wx = 0, ct = &uchp->conn_table[0];
  532.         wx < uchp->num_conns; wx++, UPDWXP(ct,sizewts) ) {
  533.       if ( (ct->flag & (CN_DISABLED|CN_WT_MASK)) != CN_VAR )
  534.          continue;     /* Not a variable weight */
  535.       /* compute the weight change */
  536.       wv = lcoef * ct->src_pe->out_val + LCOEF2 * ct->last_dw;
  537.       ct->last_dw = wv;
  538.       ct->weight += wv;
  539.    }
  540.    return ( 0 );
  541. }
  542. #endif
  543.  
  544.  
  545. #endif /* not DPK */
  546.  
  547. /* setup_umath is called just once as part of NeuralWorks initialization code.
  548.    It is used to bind user names and function pointers to the function
  549.    indices. */
  550. #endif /* DPTEST */
  551.  
  552. #ifndef TRANS_PHYS
  553. #ifndef DPTEST
  554.  
  555. GLOBALREF  NINT DR_Sum, DR_Tran, DR_Compf, DR_Learn, DR_ErrF, DR_Noise;
  556.  
  557. IMPORT  NINT AddUserFunction ARGLIST(( NINT *, NINT, TEXT *, TEXT *, 
  558.                                       NINT (*)(), NINT, NINT ));
  559.  
  560. /* The arguments to AddUserFunction ( dir, index, my_name, menu_name, 
  561.    FNP(fn_ptr), min_nwtflds , default_nwtflds)
  562.    
  563.    are as follows :
  564.    
  565.    > a pointer to one of the following "directories" -
  566.    DR_Sum, DR_Tran, DR_Compf, DR_Learn, DR_ErrF, DR_Noise -
  567.    which must not be modified in any fashion!
  568.    
  569.    > index of the function
  570.    
  571.    > the actual name of the function as it appears in the C code 
  572.    ( used to generate Designer Pack code )
  573.    
  574.    > name of the function to appear on the Layer Edit menu
  575.    
  576.    > actual function address, which will be bound to the layer; example
  577.    FNP(um_l_whatsit). The FNP macro is needed to work properly with Designer
  578.    Pack.
  579.    
  580.    > minimum number of "weight fields" the function requires.
  581.    
  582.    > default number of "weight fields" the function requires.
  583.    */
  584.  
  585. #ifdef DPK
  586. #define FNP(a)  0
  587. #else
  588. #define FNP(a)  a
  589. #endif /* not DPK */
  590. #endif /* DPTEST */
  591.    
  592. NINT  setup_umath( NO_ARGS )
  593. {
  594. #ifndef DPTEST
  595.    /* Sum functions */
  596.    
  597. #ifdef USER_BACKPROP
  598.    AddUserFunction(&DR_Sum,  LS_USER1, 
  599.                    "um_s_backprop", "bkpstdSum", FNP(um_s_backprop), 1, 1);
  600. #endif
  601.    
  602.    /* Transfer functions */
  603. #ifdef USER_BACKPROP
  604.    AddUserFunction(&DR_Tran, LT_USER3,
  605.                    "um_t_backprop", "bkpstdTran", FNP(um_t_backprop), 1, 1);
  606. #endif
  607.    
  608.    
  609.    /* Output functions */
  610.    
  611.    AddUserFunction(&DR_Compf,  LU_USER1,
  612.                    "um_o_pnn", "PNN",  FNP(um_o_pnn), 1, 1);
  613.    
  614.    /* export Error functions */
  615.    
  616. #ifdef USER_BACKPROP
  617.    AddUserFunction(&DR_ErrF, LE_USER1,
  618.                    "um_e_backprop", "bkpstderr", FNP(um_e_backprop), 1, 1);
  619. #endif
  620.    
  621.    /* Learn functions */
  622.    
  623.    AddUserFunction(&DR_Learn,  LL_USER1,
  624.                    "um_l_kohonen", "User Kohonen", FNP(um_l_kohonen), 2, 2);
  625. #ifdef USER_BACKPROP
  626.    AddUserFunction(&DR_Learn,  LL_USER3,
  627.                    "um_l_backprop", "bkpstdLrn", FNP(um_l_backprop), 2, 2);
  628. #endif
  629. #endif /* Not DPTEST */
  630.    return(0);
  631. }
  632. #endif /* not TRANS_PHYS */
  633.  
  634.